#ifndef LINKLIST_H
#define LINKLIST_H

#include "List.h"
#include "Exception.h"

namespace DTLib
{

template<typename T>
class LinkList : public List<T>
{
protected:
    struct Node : public Object {
        T value;
        Node* next;
    };

    /*
    C++编译器在实现const的成员函数时，为了确保该函数不能修改类的实例状态，会在函数中添加一个隐式的参数const this，这样类的成员变量的值，即成员变量为read only。
    */
    mutable Node m_header;
    int m_length;
public:
    LinkList()
    {
        m_header.next = NULL;
        m_length = 0;
    }

    bool insert(const T& e) // 插入到最后
    {
        return insert(m_length, e);
    }

    bool insert(int i, const T& e)
    {
        bool ret = ((0 <= i) && (i <= m_length));
        if (ret)
        {
            Node* node = new Node();
            if (node)
            {
                Node* current = &m_header;
                for (int p = 0; p < i; p++)
                {
                    current = current->next;
                }
                
                node->value = e;
                node->next = current->next;
                current->next = node;

                m_length++;
            }
            else
            {
                THROW_EXCEPTION(NoEnoughMemoryException, "No memery to insert new element...");
            }
        }

        return ret;
    }

    bool remove(int i)
    {
        bool ret = ((0 <= i) && (i < m_length));
        if (ret)
        {
            Node* current = &m_header;
            for (int p = 0; p < i; p++)
            {
                current = current->next;
            }

            Node* toDel = current->next;
            current->next = toDel->next;
            delete toDel;

            m_length--;
        }

        return ret;
    }

    bool set(int i, const T& e)
    {
        bool ret = ((0 <= i) && (i < m_length));
        if (ret)
        {
            Node* current = &m_header;
            for (int p = 0; p < i; p++)
            {
                current = current->next;
            }

            current->next->value = e;
        }

        return ret;
    }

    T get(int i) const
    {
        T ret;
        if (get(i, ret))
        {
            return ret;
        }
        else
        {
            THROW_EXCEPTION(IndexOutOfBoundsException, "Invalid parameter i to get element ...");
        }

        return ret;
    }

    bool get(int i, T& e) const
    {
        bool ret = ((0 <= i) && (i < m_length));
        if (ret)
        {
            Node* current = &m_header;
            for (int p = 0; p < i; p++)
            {
                current = current->next;
            }

            e = current->next->value;
        }

        return ret;
    }

    int length() const
    {
        return m_length;
    }

    void clear()
    {
        while (m_header.next)
        {
            Node* toDel = m_header.next;
            m_header.next = toDel->next;
            delete toDel;
        }

        m_length = 0;
    }

    ~LinkList()
    {
        clear();
    }

};

}

#endif
